package com.yijianonghu.service.wxwebsite.shoppingcart;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.yijianonghu.dal.model.BlogSpec;
import com.yijianonghu.dal.model.BlogSpecExample;
import com.yijianonghu.dal.model.SysBlog;
import com.yijianonghu.dal.model.SysBlogExample;
import com.yijianonghu.dal.model.SysCart;
import com.yijianonghu.dal.model.SysCartExample;
import com.yijianonghu.util.Constants;
import com.yijianonghu.util.DBUtils;
import com.yijianonghu.util.exception.ExceededLimitException;
import com.yijianonghu.util.exception.InvalidArgumentException;
import com.yijianonghu.util.exception.NoResultReturnedException;
import com.yijianonghu.util.result.MessageCode;

import net.javahub.dao.BaseSqlDao;
import net.javahub.dao.BaseSqlDao.SqlWrapper;
import net.javahub.dao.IBaseDao;
import net.javahub.service.BaseTransactionalService;

@Service
public class ShoppingCartService extends BaseTransactionalService<SysCart, Integer, SysCartExample> {

	private static final Logger logger = LoggerFactory.getLogger(ShoppingCartService.class);

	@Autowired
	private BaseSqlDao baseSqlDao;

	@Autowired
	private IBaseDao<SysBlog, Integer, SysBlogExample> sysBlogDao;

	@Autowired
	private IBaseDao<BlogSpec, Integer, BlogSpecExample> blogSpecDao;

	public Long getShoppingCartCount(Integer userId) throws Exception{
		String sql="select sum(buycount) from sys_cart mt left join sys_blog s on mt.keyid=s.id where s.saleflag=1 and mt.client_id=#{params.client_id} and mt.statetype=1";
		SqlWrapper sqlWrapper=new SqlWrapper();
		sqlWrapper.setSqlStatement(sql);
		sqlWrapper.addParam("client_id", userId);
		List<Map<String, Object>> buyCountList=baseSqlDao.select(sqlWrapper);
		Long buyCount=0l;
		if(DBUtils.isFirstItemOfListNotEmpty(buyCountList)){
			List<Object> list=new ArrayList<Object>(buyCountList.get(0).values());
			if(DBUtils.isFirstItemOfListNotEmpty(list)){
				buyCount=DBUtils.parseToNumber(Long.class, list.get(0));
			}
		}
		if(buyCount==null || buyCount<0){
			buyCount=0l;
		}
		return buyCount;
	}
	
	public List<Map<String, Object>> saveOperateShoppingCart(Integer userId, Integer id, Integer keyType, Integer buyCount) throws Exception {
		String sql = null;
		SqlWrapper sqlWrapper = new SqlWrapper();
		sqlWrapper.addParam("id", id);
		sqlWrapper.addParam("client_id", userId);
		SysCartExample sysCartExample = new SysCartExample();
		List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
		if (1 == keyType) {
			// 单个删除
			sysCartExample.createCriteria()
				.andIdIsNotNull()
				.andIdEqualTo(id)
				.andClientIdIsNotNull()
				.andClientIdEqualTo(userId);
			
			List<SysCart> sysCartList = baseDao.selectByExample(SysCart.class, sysCartExample);
			if (DBUtils.isListNotEmpty(sysCartList)) {
				for (SysCart sysCart : sysCartList) {
					sysCart.setStatetype((byte) 4);
				}
				baseDao.batchUpdateByPrimaryKey(SysCart.class, sysCartList);
				return resultList;
			} else {
				throw new NoResultReturnedException("没有购物车项！");
			}
		} else if (2 == keyType) {
			// 清空购物车
			sysCartExample.createCriteria()
				.andClientIdIsNotNull()
				.andClientIdEqualTo(userId)
				.andStatetypeIsNotNull()
				.andStatetypeEqualTo((byte) 1);
			List<SysCart> sysCartList = baseDao.selectByExample(SysCart.class, sysCartExample);
			if (DBUtils.isListNotEmpty(sysCartList)) {
				for (SysCart sysCart : sysCartList) {
					sysCart.setStatetype((byte) 4);
				}
				baseDao.batchUpdateByPrimaryKey(SysCart.class, sysCartList);
				return resultList;
			} else {
				throw new NoResultReturnedException("未找到购物车！");
			}
		} else if (3 == keyType) {
			// 更改购买数量，查询相关商品信息
			if (buyCount < 1) {
				buyCount = 1;
			}
			sql = "select mt.keyid,b.leftcount,b.limitcount,mt.specid from sys_cart mt left join sys_blog b on mt.keyid=b.id where mt.id=#{params.id}";
			sqlWrapper.setSqlStatement(sql);
			resultList = baseSqlDao.select(sqlWrapper);
			if (DBUtils.isFirstItemOfListNotEmpty(resultList)) {
				Object leftCount = null;
				Object blogLimitCount = null;
				if (resultList.get(0).get("specid") != null && (!DBUtils.isEqualInteger(Constants.CommonConstants.INTEGER_ZERO, resultList.get(0).get("specid")))) {
					sql = "select leftcount,limitcount from 3_blog_spec where id=#{params.specid}";
					sqlWrapper.setSqlStatement(sql);
					sqlWrapper.addParam("specid", resultList.get(0).get("specid"));
					List<Map<String, Object>> specDataList = baseSqlDao.select(sqlWrapper);
					if (DBUtils.isFirstItemOfListNotEmpty(specDataList)) {
						leftCount = specDataList.get(0).get("leftCount");
						blogLimitCount = specDataList.get(0).get("limitcount");
					}
				} else {
					leftCount = resultList.get(0).get("leftcount");
					blogLimitCount = resultList.get(0).get("limitcount");
				}
				if (!DBUtils.isEqualInteger(Constants.CommonConstants.INTEGER_ZERO, blogLimitCount)) {
					Integer keyId = DBUtils.parseToNumber(Integer.class, resultList.get(0).get("keyid"));
					sql = "select sum(buycount) from 3_limitbuy_record where client_id=#{params.client_id} and keytype=1 and keyid=#{params.keyid} and specid=#{params.specid}";
					sqlWrapper.setSqlStatement(sql);
					sqlWrapper.addParam("keyid", keyId);
					List<Map<String, Object>> clientBuyCountList = baseSqlDao.select(sqlWrapper);
					if (DBUtils.isFirstItemOfListNotEmpty(clientBuyCountList)) {
						List<Object> list = new ArrayList<Object>(clientBuyCountList.get(0).values());
						Long clientBuyCount = null;
						if (DBUtils.isFirstItemOfListNotEmpty(list)) {
							clientBuyCount = DBUtils.parseToNumber(Long.class, list.get(0));
						} else {
							clientBuyCount = 0l;
						}
						if ((clientBuyCount + buyCount) > DBUtils.parseToNumber(Long.class, blogLimitCount)) {
							logger.error("购买数量超过限购数量！buyCount:" + buyCount + ", clientBuyCount:" + clientBuyCount
									+ ", limitCount:" + blogLimitCount);
							throw new ExceededLimitException("购买数量超过限购数量");
						}
					}
				}

				if (DBUtils.parseToNumber(Integer.class, leftCount) < buyCount) {
					logger.error("库存不足！buyCount:" + buyCount + ", 库存：" + leftCount);
					throw new ExceededLimitException("库存不足！");
				}
				
				sysCartExample.createCriteria()
					.andIdIsNotNull()
					.andIdEqualTo(id)
					.andClientIdIsNotNull()
					.andClientIdEqualTo(userId);
				List<SysCart> sysCartList=baseDao.selectByExample(SysCart.class, sysCartExample);
				if(DBUtils.isFirstItemOfListNotEmpty(sysCartList)){
					SysCart sysCart=sysCartList.get(0);
					sysCart.setBuycount(buyCount);
					baseDao.updateByPrimaryKey(sysCart);
				}
			} else {
				throw new NoResultReturnedException("未找到购物车商品对应信息！");
			}
		} else if(4==keyType){
			//清空过期购物车
			sysCartExample.createCriteria()
			.andClientIdIsNotNull()
			.andClientIdEqualTo(userId)
			.andStatetypeIsNotNull()
			.andStatetypeEqualTo((byte) 2);
			List<SysCart> sysCartList=baseDao.selectByExample(SysCart.class, sysCartExample);
			if(DBUtils.isFirstItemOfListNotEmpty(sysCartList)){
				for(SysCart sysCart:sysCartList){
					sysCart.setStatetype((byte) 4);
				}
				baseDao.batchUpdateByPrimaryKey(SysCart.class, sysCartList);
			}
		} else {
			logger.error("keytype取值范围不正确！keytype: "+keyType);
			throw new InvalidArgumentException("keytype取值范围不正确！");
		}
		return resultList;
	}

	public MessageCode addToShoppingCart(Integer userId, Integer keyId, Integer buyCount, Integer specId)
			throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException, NoResultReturnedException, InstantiationException {

		Date regDate = new Date();
		Date endDate = new Date(regDate.getTime() + (1000 * 30 * 60));

		SysCartExample sysCartExample = new SysCartExample();
		// 查看购物车是否已有该商品
		sysCartExample.createCriteria().andClientIdIsNotNull().andClientIdEqualTo(userId).andKeyidIsNotNull()
				.andKeyidEqualTo(keyId).andSpecidIsNotNull().andSpecidEqualTo(specId).andStatetypeIsNotNull()
				.andStatetypeEqualTo((byte) 1);
		List<SysCart> preCartList = selectListByExample(SysCart.class, sysCartExample);
		Integer preBuyCount = null;
		if (preCartList != null && (!preCartList.isEmpty())) {
			preBuyCount = preCartList.get(0).getBuycount();
		}

		// 查看商品是否下架，是否有库存
		SysBlog sysBlog = sysBlogDao.selectByPrimaryKey(SysBlog.class, keyId);
		if (sysBlog == null || (sysBlog.getSaleflag() == 0)) {
			logger.info("加入购物车的商品获取失败： " + sysBlog + ((sysBlog == null) ? "。" : "商品已下架。"));
			return MessageCode.PAGE_NOT_FOUND;
		}

		String name = sysBlog.getName();
		String oneSpec = sysBlog.getOneSpec();
		String twoSpec = sysBlog.getTwoSpec();
		Integer limitCount = sysBlog.getLimitcount();

		Integer leftCount = null;// 库存
		Double price = null;
		Double score = null;
		Integer scorePercent = null;

		if (specId == 0) {
			leftCount = sysBlog.getLeftcount();// 库存
			price = sysBlog.getPrice();
			score = sysBlog.getScore();
			scorePercent = sysBlog.getScorePercent();
		} else {
			BlogSpecExample blogSpecExample = new BlogSpecExample();
			blogSpecExample.createCriteria().andBlogIdIsNotNull().andBlogIdEqualTo(keyId).andIdIsNotNull()
					.andIdEqualTo(specId).andRemoveflagIsNotNull().andRemoveflagEqualTo((byte) 0);
			List<BlogSpec> blogSpecList = blogSpecDao.selectByExample(BlogSpec.class, blogSpecExample);
			if (blogSpecList == null || blogSpecList.isEmpty()) {
				throw new NoResultReturnedException("获取规格失败，id: " + specId);
			}
			BlogSpec blogSpec = blogSpecList.get(0);
			leftCount = blogSpec.getLeftcount();
			price = blogSpec.getPrice();
			score = blogSpec.getScore();
			scorePercent = Integer.valueOf(blogSpec.getScorePercent());
			limitCount = blogSpec.getLimitcount();
		}

		if (preBuyCount != null && preBuyCount != 0) {
			buyCount += preBuyCount;
		}
		if (buyCount < 1) {
			buyCount = 1;
		}

		// 检测商品库存
		if (sysBlog.getType() != 1 && leftCount < buyCount) {
			logger.info("商品加入购物车失败： " + sysBlog + "。 商品库存不足。库存：" + leftCount + ", 购买数量： " + buyCount);
			return MessageCode.COMMON_INSUFFICIENT_SKU;
		}

		if (limitCount != null && limitCount > 0) {
			// $sqlstr="select sum(buycount) from 3_limitbuy_record where
			// client_id=$client_id and keytype=1 and keyid=$keyid and
			// specid=$specid";
			SqlWrapper sqlWrapper = new SqlWrapper();
			sqlWrapper.setSqlStatement(
					"select sum(buycount) from 3_limitbuy_record where client_id=#{client_id} and keytype=1 and keyid=#{keyid} and specid=#{specid}");
			sqlWrapper.addParam("client_id", userId);
			sqlWrapper.addParam("keyid", keyId);
			sqlWrapper.addParam("specid", specId);
			Long clientBuyCount = baseSqlDao.selectOne(sqlWrapper, Long.class);
			clientBuyCount = (clientBuyCount == null) ? 0 : clientBuyCount;
			if ((clientBuyCount + buyCount) > limitCount) {
				logger.info("商品加入购物车失败： " + sysBlog + "。 超过限购数量。限购：" + limitCount + ", 购买数量：" + buyCount + ", 商品已购买总数："
						+ clientBuyCount);
				return MessageCode.COUNT_EXCEEDED;
			}
		}

		if (preBuyCount == null || preBuyCount == 0) {
			SysCart sysCart = new SysCart();
			sysCart.setClientId(userId);
			sysCart.setKeyid(keyId);
			sysCart.setName(name);
			sysCart.setPrice(price);
			sysCart.setScore(score);
			sysCart.setScorePercent(scorePercent);
			sysCart.setBuycount(buyCount);
			sysCart.setSpecid(specId);
			sysCart.setOneSpec(oneSpec);
			sysCart.setTwoSpec(twoSpec);
			sysCart.setRegdate(regDate);
			sysCart.setEnddate(endDate);
			sysCart.setStatetype((byte) 1);
			baseDao.insert(sysCart);
		} else {
			SysCart sysCart = preCartList.get(0);
			sysCart.setBuycount(buyCount);
			baseDao.updateByPrimaryKey(sysCart);
		}
		return MessageCode.COMMON_SUCCESS;
	}

	public Map<Object, Map<String, Object>> listShoppingCart(Integer userId) throws Exception {
		SqlWrapper sqlWrapper = new SqlWrapper();
		StringBuilder sb = new StringBuilder(
				"select mt.*,s.unit,s.expressfee,s.imgurl,s.imgurlbig,s.client_id as seller_id,sc.nickname as seller_name,bs.one_specname,bs.two_specname ");
		sb.append(" from sys_cart mt").append(" left join sys_blog s on mt.keyid=s.id")
				.append(" left join 3_blog_spec bs on mt.specid=bs.id")
				.append(" left join sys_client sc on s.client_id=sc.id")
				.append(" where s.saleflag=1 and mt.client_id=#{params.client_id} and mt.statetype=1 order by seller_id asc");
		sqlWrapper.setSqlStatement(sb.toString());
		sqlWrapper.addParam("client_id", userId);
		List<Map<String, Object>> shoppingCartList = baseSqlDao.select(sqlWrapper);
		Map<Object, Map<String, Object>> shoppingCarts = new HashMap<Object, Map<String, Object>>();
		if (shoppingCartList != null && (!shoppingCartList.isEmpty())) {
			for (Map<String, Object> shoppingCart : shoppingCartList) {
				Double subTotal = null;
				Double price = DBUtils.<Double>parseToNumber(Double.class, shoppingCart.get("price"));
				Integer buyCount = DBUtils.<Integer>parseToNumber(Integer.class, shoppingCart.get("buycount"));
				subTotal = price * buyCount;
				shoppingCart.put("subtotal", subTotal);
				if (shoppingCarts.get(shoppingCart.get("seller_id")) == null) {
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("seller_id", shoppingCart.get("seller_id"));
					shoppingCarts.put(shoppingCart.get("seller_id"), map);
					if (DBUtils.isEqualInteger(Constants.CommonConstants.INTEGER_ONE, shoppingCart.get("seller_id"))) {
						map.put("seller_name", Constants.CommonConstants.PING_TAI_ZI_YING);
					} else {
						map.put("seller_name", shoppingCart.get("seller_name"));
					}
				}
				Map<String, Object> map = shoppingCarts.get(shoppingCart.get("seller_id"));
				Double totalFee = (map.get("total_fee") == null ? 0.0
						: DBUtils.parseToNumber(Double.class, map.get("total_fee")));
				totalFee += subTotal;
				map.put("total_fee", totalFee);
				Object childItemsObject = map.get("childItems");
				if (childItemsObject == null) {
					List<Object> childItems = new ArrayList<Object>();
					map.put("childItems", childItems);
					childItemsObject = childItems;
				}
				List<Object> childItems = (List<Object>) childItemsObject;
				childItems.add(shoppingCart);
			}
		}
		return shoppingCarts;
	}

}
